もう並列実行は怖くない コネクション枯渇とデッドロック解決の実践的アプローチ
Ruby on Railsを使ったアプリケーションのサービス拡大により、大量データのバッチ処理をRakeタスクで書くという経験はみなさんにもあると思います。より高速化する上で並列処理というのはアプローチの一つとしてあると思いますが、 Rakeタスクの並列化で突如牙を剥くDBコネクションプール枯渇、そして気づかぬうちに忍び寄るデッドロックは多くの開発者を悩ませる根深い問題です。本セッションでは、取り扱う商品数が1000万点を超える弊社マイベストが実際に直面し、実際の案件、失敗例を元にActive Recordのコネクションプールとトランザクションの詳しい仕組みと、RAILS_MAX_THREADSやpoolサイズ、ロック取得順序がサービスにどのように影響するのかを説明します。ECS環境での具体的な設定例から、デッドロックを回避するコード戦略まで、試行錯誤とそこから得た実践的な知見やパラメータの設定方法など共有します。 https://scrapbox.io/files/68d626cf0f8155cc19594d2c.jpeg
オールジャンルのDB大変そう
商品のタイプによって登録する情報が違う
例)日傘ならUVカット率
AIでのデータ登録をプロダクトに載せる話
日次バッチ、管理画面から実行
課題: 時間がかかる
1商品2分
スレッド数が少なくJobが詰まる
ので、並列実行
マルチスレッドで実行
コネクションプールが枯渇
スレッド数に対してコネクションプールのサイズが少ない
スレッド数<=コネクションプール数にしないといけない
pumaのプロセス数も増やす
新しいjobを定義してほかと競合しないようにした
sidekiqの場合はコネクションプール数+1のプロセスが必要
安全に行うために
悲観的に見積もる
DB側のMAX CONNECTIOSNS
ECSのタスク数
この計算だとECSがスケールしたら死ぬ?→スケールも計算するっぽい
全体のコネクション数はRDSのコネクション数の半数以下にする
リリース時に旧環境と共存するため
Sidekiqは1プロセス50こんかれんしー
with_connection
コネクションを占有しすぎないようにする
注意点
長時間のトランザクションは張らない
rack-lineprof
トランザクション内で外部IOが発生する箇所に気付けた